package cn.itcast.mq.listener;

import com.rabbitmq.client.Channel;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.Exchange;
import org.springframework.amqp.rabbit.annotation.Queue;
import org.springframework.amqp.rabbit.annotation.QueueBinding;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;

import java.io.IOException;

@Component
@Slf4j
public class SpringRabbitListener {

    /**
     * 测试SpringAMQP确认模式
     * auto(默认)：自动ack，由spring监测listener代码是否出现异常，没有异常返回ack；有异常返回nack（默认）；
     * auto默认方式，消费者消息处理异常后消息会重新入队，不会删除信息，如果消费者一直异常则会一直死循环。
     */
    /*
    @RabbitListener(queues = "simple.queue")
    public void listenSimpleQueue(String msg) {
        log.debug("消费者接收到simple.queue的消息：【" + msg + "】");
        System.out.println(1/0);
        log.debug("消费者处理消息成功了");
    }
    */

    /**
     * 测试SpringAMQP确认模式
     * none：关闭ack，MQ假定消费者获取消息后会成功处理，因此消息投递后立即被删除
     * @param msg
     */
    /*
    @RabbitListener(queues = "simple.queue")
    public void listenSimpleQueue(String msg) {
        log.debug("消费者接收到simple.queue的消息：【" + msg + "】");
        System.out.println(1/0);
        log.debug("消费者处理消息成功了");
    }
    */

    /**
     * 测试SpringAMQP确认模式
     * manual：
     * 手动ack，需要在业务代码结束后，调用api发送ack。
     * 出现异常后可以重新将消息放入队列中，跟auto效果一样，不会删除信息，一直异常会导致死循环。
     * @param msg
     * @param channel
     * @param message
     * @throws IOException
     */
    /*
    @RabbitListener(queues = "simple.queue")
    public void listenSimpleQueue(String msg, Channel channel, Message message) throws IOException {
        log.debug("消费者接收到simple.queue的消息：【" + msg + "】");
        try {
            System.out.println(1/0);
            //ack  channel基于通过进行ack nack
            //参数1：消息唯一1（哪条消息应答） multiple:true(批量应答消息) false(一个一个应答消息)
            channel.basicAck(message.getMessageProperties().getDeliveryTag(),false);
        } catch (Exception e) {
            //nack requeue:重新放入队列中;跟auto效果一样，会导致死循环
            channel.basicNack(message.getMessageProperties().getDeliveryTag(),false,true);
        }
    }
    */

    /**
     * 死信交换机
     * @param msg
     */
    @RabbitListener(bindings =
    @QueueBinding(
            value = @Queue(name = "dl.queue", durable = "true"),
            exchange = @Exchange(name = "dl.direct"),
            key = "dl")
    )
    public void listenDlQueue(String msg) {
        log.info("接收到 dl.queue的延迟消息：{}", msg);
    }

    /**
     * RabbitMQ官方推荐使用-延迟插件
     */
    @RabbitListener(bindings =
    @QueueBinding(
            value = @Queue(name = "delay.queue"),
            exchange = @Exchange(name = "delay.direct",delayed = "true"),
            key = "delay")
    )
    public void listenDelayQueue(String msg) {
        log.info("接收到 delay.queue的延迟消息：{}", msg);
    }

}
